package remato.domain.server.ejb;

import static javax.persistence.CascadeType.ALL;
import static javax.persistence.GenerationType.AUTO;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

import remato.domain.common.Category;
import remato.domain.common.CategoryParentable;
import remato.domain.common.Project;
import remato.domain.common.PropertySet;
import remato.domain.common.Requirement;
import remato.domain.common.impl.CategoryImpl;

import com.wgo.bpot.common.transport.exception.RematoException;

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class CategoryEjb extends CategoryImpl implements Category, CategoryParentable{
	private Project projectParent;
	private Category categoryParent;

	@Override
	@Id
	@GeneratedValue(strategy=AUTO)
	public Long getDbId() {
		return super.getDbId();
	}

	@Override
	@Lob
	public String getDescription() {
		return super.getDescription();
	}

	@Override
	public String getName() {
		return super.getName();
	}

	@Override
	@Transient
	public CategoryParentable getCategoryParent() {
		return null != categoryParent ? categoryParent : projectParent;  
	}

	@Override
	public void setCategoryParent(CategoryParentable parent) {
		if (parent instanceof Project) {
			setProjectParentField((Project)parent);
			setCategoryParentField(null);
		} else if (parent instanceof Category) {
			setCategoryParentField((Category)parent);
			setProjectParentField(null);
		} else if (null == parent){
			setCategoryParentField(null);
			setProjectParentField(null);
		} else {
			throw new RematoException("Category's parent is of unknown type: " + parent.getClass());
		}
	}

	@ManyToOne(targetEntity = CategoryEjb.class)
	protected Category getCategoryParentField() {
		return categoryParent;
	}

	protected void setCategoryParentField(Category categoryParent) {
		this.categoryParent = categoryParent;
	}

	@ManyToOne(targetEntity = ProjectEjb.class)
	protected Project getProjectParentField() {
		return projectParent;
	}

	protected void setProjectParentField(Project projectParent) {
		this.projectParent = projectParent;
	}

	@Override
	@OneToMany(mappedBy = "category", targetEntity = RequirementEjb.class, cascade = { ALL })
	public Set<Requirement> getRequirements() {
		return super.getRequirements();
	}

	@Override
	@OneToMany(mappedBy = "categoryParentField", targetEntity = CategoryEjb.class, cascade = { ALL })
	public Set<Category> getCategoryChildren() {
		return super.getCategoryChildren();
	}

	@Override
    @ManyToMany( targetEntity = PropertySetEjb.class, cascade ={ALL} )
    @JoinTable(
    		name="CATEGORY_PROPERTYDEFSET",
            joinColumns={@JoinColumn(name="CATEGORY_ID")},
            inverseJoinColumns={@JoinColumn(name="PROPERTYDEFSET_ID")} )
	public Set<PropertySet> getPropertySets() {
		return super.getPropertySets();
	}

	/**
	 * Needed to trigger CGLib proxy (ie. if other CGLib-proxies is used as 
	 * parameter.)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		return super.equals(obj);
	}

}
